/***************************************************************
 *  Copyright (c) 2007 by Personal Reader Team (www.personal-reader.de)
 *  All rights reserved
 *
 *  This file is part of the Personal Reader Connector. The Personal Reader 
 *  Connector is free software; you can redistribute it and/or modify it
 *  under the terms of the GNU General Public License as published by the
 *  Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 * 
 *  The GNU General Public License can be found at
 *  http://www.gnu.org/copyleft/gpl.html.
 * 
 *  This file is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  This copyright notice MUST APPEAR in all copies of the file!
 ***************************************************************/
package net.groupme.model.dao;

import java.net.URI;
import java.net.URISyntaxException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import javax.sql.DataSource;

import net.groupme.exceptions.DeleteFailedException;
import net.groupme.exceptions.DuplicateUsernameException;
import net.groupme.exceptions.InsertFailedException;
import net.groupme.exceptions.UpdateFailedException;
import net.groupme.exceptions.UserNotExistingException;
import net.groupme.gui.constants.VIEW_VOCABULARY;
import net.groupme.model.Group;
import net.groupme.model.GroupVisualization;
import net.groupme.model.GroupVisualizationImpl;
import net.groupme.model.Resource;
import net.groupme.model.Tag;
import net.groupme.utils.sql.CheckPasswordQuery;
import net.groupme.utils.sql.GetGroupVisualizationsQuery;
import net.groupme.utils.sql.GetGroupsQuery;
import net.groupme.utils.sql.GetStringFromTableWhereIDQuery;
import net.groupme.utils.sql.GetStringQuery;
import net.groupme.utils.sql.GetTagsQuery;

import org.apache.log4j.Logger;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.object.SqlUpdate;
import org.springframework.jdbc.support.GeneratedKeyHolder;

/**
 * This class implements a DAO for the User implementation.
 * 
 * @author Mischa Frank <a
 *         href="mailto:code@planetfrank.net">code@planetfrank.net</a>
 * @author Patrick Siehndel <a
 *         href="mailto:patrick.siehndel@gmx.de">patrick.siehndel@gmx.de</a>
 * 
 * @version 1.0, created on 20/04/2007
 * 
 */
public class UserDAOImpl implements UserDAO {

	// table
	private static final String TABLE_USERGROUP = DBProperties
			.getString("GroupmeDB.TABLE_USERGROUP"); //$NON-NLS-1$

	// columns
	private static final String USERGROUP_USER_ID = DBProperties
			.getString("GroupmeDB.USERGROUP_USER_ID"); //$NON-NLS-1$

	private static final String USERGROUP_GROUP_ID = DBProperties
			.getString("GroupmeDB.USERGROUP_GROUP_ID"); //$NON-NLS-1$

	private static final String USERGROUP_ROLE = DBProperties
			.getString("GroupmeDB.USERGROUP_ROLE"); //$NON-NLS-1$

	// table
	private static final String TABLE_USER = DBProperties
			.getString("GroupmeDB.TABLE_USER"); //$NON-NLS-1$

	// columns
	private static final String USER_EMAIL = DBProperties
			.getString("GroupmeDB.USER_EMAIL"); //$NON-NLS-1$

	private static final String USER_FIRSTNAME = DBProperties
			.getString("GroupmeDB.USER_FIRSTNAME"); //$NON-NLS-1$

	private static final String USER_LASTNAME = DBProperties
			.getString("GroupmeDB.USER_LASTNAME"); //$NON-NLS-1$
	
	private static final String USER_FOAF = DBProperties
			.getString("GroupmeDB.USER_FOAF"); //$NON-NLS-1$

	private static final String USER_PASSWORD = DBProperties
			.getString("GroupmeDB.USER_PASSWORD"); //$NON-NLS-1$

	private static final String USER_ID = DBProperties
			.getString("GroupmeDB.USER_ID"); //$NON-NLS-1$

	private static final String USER_USERNAME = DBProperties
			.getString("GroupmeDB.USER_USERNAME"); //$NON-NLS-1$

	// table
	private static final String TABLE_USERGROUPVISUALIZATION = DBProperties
			.getString("GroupmeDB.TABLE_USERGROUPVISUALIZATION"); //$NON-NLS-1$

	// columns
	private static final String USERGROUPVISUALIZATION_VISUALIZATION_ID = DBProperties
			.getString("GroupmeDB.USERGROUPVISUALIZATION_VISUALIZATION_ID"); //$NON-NLS-1$

	private static final String USERGROUPVISUALIZATION_USER_ID = DBProperties
			.getString("GroupmeDB.USERGROUPVISUALIZATION_USER_ID"); //$NON-NLS-1$

	private static final String USERGROUPVISUALIZATION_GROUP_ID = DBProperties
			.getString("GroupmeDB.USERGROUPVISUALIZATION_GROUP_ID"); //$NON-NLS-1$

	private static final String USERGROUPVISUALIZATION_ACTUAL = DBProperties
			.getString("GroupmeDB.USERGROUPVISUALIZATION_ACTUAL"); //$NON-NLS-1$

	// table
	private static final String TABLE_USERTAGGROUPRESOURCE = DBProperties
			.getString("GroupmeDB.TABLE_USERTAGGROUPRESOURCE"); //$NON-NLS-1$

	// columns
	private static final String USERTAGGROUPRESOURCE_TAGID = DBProperties
			.getString("GroupmeDB.USERTAGGROUPRESOURCE_TAGID"); //$NON-NLS-1$

	private static final String USERTAGGROUPRESOURCE_USERID = DBProperties
			.getString("GroupmeDB.USERTAGGROUPRESOURCE_USERID"); //$NON-NLS-1$

	private static final String USERTAGGROUPRESOURCE_RESOURCEID = DBProperties
			.getString("GroupmeDB.USERTAGGROUPRESOURCE_RESOURCEID"); //$NON-NLS-1$

	/** Logger for this class and subclasses */
	private static final Logger log = Logger.getLogger(UserDAOImpl.class);

	private DataSource ds;

	private String id = null;

	private String query;

	/**
	 * Creates a new user by resolving the id of the user according to the given
	 * username.
	 * 
	 * @param dataSource
	 *            the data source
	 * @param name
	 *            the username
	 * @throws UserNotExistingException
	 */
	public UserDAOImpl(DataSource dataSource, String name)
			throws UserNotExistingException {
		this.ds = dataSource;

		query = "SELECT " + USER_ID + " FROM " + TABLE_USER + " WHERE "
				+ USER_USERNAME + " = \"" + name + "\"";
		GetStringQuery queryExecution = new GetStringQuery(ds, query, USER_ID);
		List ids = queryExecution.execute();
		if (ids != null && !ids.isEmpty()) {
			this.id = ids.iterator().next().toString();
		} else if (ids.isEmpty()) {
			throw new UserNotExistingException();
		}
		log.debug("username: " + name + " - id: " + this.id);
	}

	/**
	 * Creates a new user object by the given id.
	 * 
	 * @param dataSource
	 *            the data source
	 * @param id
	 *            the userId
	 * @throws UserNotExistingException
	 */
	public UserDAOImpl(DataSource dataSource, Integer id)
			throws UserNotExistingException {
		this.ds = dataSource;

		GetStringFromTableWhereIDQuery queryExecution = new GetStringFromTableWhereIDQuery(
				ds, USER_USERNAME, TABLE_USER, id.toString());
		List userNames = queryExecution.execute();
		if (userNames.isEmpty()) {
			throw new UserNotExistingException();
		} else {
			this.id = id.toString();
		}
	}

	public UserDAOImpl(DataSource dataSource, String userName,
			String firstName, String lastName, String email, String password)
			throws InsertFailedException, DuplicateUsernameException {
		try {
			this.ds = dataSource;
			SqlUpdate su = new SqlUpdate(ds, "INSERT INTO " + TABLE_USER //$NON-NLS-1$
					+ " (" + USER_USERNAME + ", " + USER_FIRSTNAME + ", "
					+ USER_LASTNAME + ", " + USER_EMAIL + ", " + USER_PASSWORD
					+ ") VALUES (?, ?, ?, ?, PASSWORD(?))");
			su.declareParameter(new SqlParameter("userName", Types.VARCHAR)); //$NON-NLS-1$
			su.declareParameter(new SqlParameter("firstName", Types.VARCHAR)); //$NON-NLS-1$
			su.declareParameter(new SqlParameter("lastName", Types.VARCHAR)); //$NON-NLS-1$
			su.declareParameter(new SqlParameter("email", Types.VARCHAR)); //$NON-NLS-1$
			su.declareParameter(new SqlParameter("password", Types.VARCHAR)); //$NON-NLS-1$
			su.compile();
			Object[] oa = new Object[5];
			oa[0] = new String(userName);
			oa[1] = new String(firstName);
			oa[2] = new String(lastName);
			oa[3] = new String(email);
			oa[4] = new String(password);
			GeneratedKeyHolder keyHolder = new GeneratedKeyHolder();
			int count = su.update(oa, keyHolder);
			if (count == 0)
				throw new InsertFailedException();
			this.id = keyHolder.getKey().toString();
		} catch (DataIntegrityViolationException e) {
			throw new DuplicateUsernameException();
		}
	}

	/* (non-Javadoc)
	 * @see net.groupme.model.User#getId()
	 */
	public String getId() {
		return this.id;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.User#addGroup(net.groupme.model.Group,
	 *      java.lang.String)
	 */
	public void addGroup(Group group, String role) throws InsertFailedException {
		SqlUpdate su = new SqlUpdate(
				ds,
				"INSERT INTO " + TABLE_USERGROUP //$NON-NLS-1$
						+ " (" + USERGROUP_USER_ID + ", " + USERGROUP_GROUP_ID + ", " + USERGROUP_ROLE + ") VALUES (?, ?, ?)"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
		su.declareParameter(new SqlParameter("uID", Types.INTEGER)); //$NON-NLS-1$
		su.declareParameter(new SqlParameter("gID", Types.INTEGER)); //$NON-NLS-1$
		su.declareParameter(new SqlParameter("role", Types.VARCHAR)); //$NON-NLS-1$
		su.compile();
		try {
			Object[] oa = new Object[3];
			oa[0] = new Integer(this.id);
			oa[1] = new Integer(group.getId());
			oa[2] = role;
			int count = su.update(oa);
			if (count == 0)
				throw new InsertFailedException();
		} catch (NumberFormatException e) {
			log.debug(e.getMessage());
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.User#addTag(net.groupme.model.Tag)
	 */
	public void addTag(Tag tag) {
		// not sure if it has to be implemented yet
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.User#addVisualization(net.groupme.model.GroupVisualization)
	 */
	public void addVisualization(GroupVisualization groupVisualization) {
		// not sure if it has to be implemented yet
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.User#getPassword()
	 */
	public boolean checkPassword(String password) {
		query = "SELECT " + USER_ID + " FROM " + TABLE_USER + " WHERE " + USER_PASSWORD + " = PASSWORD('" + password + "') AND " + USER_ID + " = " + id; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
		CheckPasswordQuery checkPassword = new CheckPasswordQuery(ds, query,
				USER_ID);
		List passwords = checkPassword.execute();
		if (passwords != null && !passwords.isEmpty()) {
			return true;
		}
		return false;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.User#getActualVisualization(net.groupme.model.Group)
	 */
	public GroupVisualization getActualVisualization(Group group) {
		query = "SELECT " + USERGROUPVISUALIZATION_VISUALIZATION_ID + " FROM " + TABLE_USERGROUPVISUALIZATION //$NON-NLS-1$ //$NON-NLS-2$
				+ " WHERE " + USERGROUPVISUALIZATION_USER_ID + " = " + id + " AND " + USERGROUPVISUALIZATION_GROUP_ID //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				+ " = " + group.getId() + " AND " + USERGROUPVISUALIZATION_ACTUAL + " = 1"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		GetStringQuery getStringQuery = new GetStringQuery(ds, query,
				USERGROUPVISUALIZATION_VISUALIZATION_ID);
		GroupVisualization actual = new GroupVisualizationImpl(
				new GroupVisualizationDAOImpl(ds, (String) getStringQuery
						.execute().iterator().next()));
		return actual;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.Identifiable#getDescription()
	 */
	public String getDescription() {
		return this.getLabel() + " " + this.getEmail(); //$NON-NLS-1$
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.User#getEmail()
	 */
	public String getEmail() {
		GetStringFromTableWhereIDQuery getEmailQuery = new GetStringFromTableWhereIDQuery(
				ds, USER_EMAIL, TABLE_USER, id);
		return (String) getEmailQuery.execute().iterator().next();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.User#getFirstName()
	 */
	public String getFirstName() {
		GetStringFromTableWhereIDQuery getFirstNameQuery = new GetStringFromTableWhereIDQuery(
				ds, USER_FIRSTNAME, TABLE_USER, id);
		return (String) getFirstNameQuery.execute().iterator().next();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.User#getGroups()
	 */
	@SuppressWarnings("unchecked")
	public Collection<Group> getGroups() {
		query = "SELECT " + USERGROUP_GROUP_ID + " FROM " + TABLE_USERGROUP + " WHERE " + USERGROUP_USER_ID + " = " + id; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
		GetGroupsQuery getGroupsQuery = new GetGroupsQuery(ds, query,
				USERGROUP_GROUP_ID);
		Iterator iter = getGroupsQuery.execute().iterator();
		if (iter.hasNext()) {
			return (Collection<Group>) iter.next();
		}
		return new ArrayList<Group>();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.User#getGroups(String role)
	 */
	@SuppressWarnings("unchecked")
	public Collection<Group> getGroups(String role) {
		query = "SELECT " + USERGROUP_GROUP_ID + " FROM " + TABLE_USERGROUP + " WHERE " + USERGROUP_USER_ID + " = " + id + " AND " + USERGROUP_ROLE + " = \"" + role + "\""; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$
		GetGroupsQuery getGroupsQuery = new GetGroupsQuery(ds, query,
				USERGROUP_GROUP_ID);
		Iterator iter = getGroupsQuery.execute().iterator();
		if (iter.hasNext()) {
			return (Collection<Group>) getGroupsQuery.execute().iterator()
					.next();
		}
		return new ArrayList<Group>();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.Identifiable#getLabel()
	 */
	public String getLabel() {
		return this.getUserName() + " " + this.getLastName(); //$NON-NLS-1$
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.User#getLastName()
	 */
	public String getLastName() {
		GetStringFromTableWhereIDQuery getLastNameQuery = new GetStringFromTableWhereIDQuery(
				ds, USER_LASTNAME, TABLE_USER, id);
		return (String) getLastNameQuery.execute().iterator().next();
	}

	
	public String getFoaf() {
		GetStringFromTableWhereIDQuery getFoafQuery = new GetStringFromTableWhereIDQuery(
				ds, "foafURL", TABLE_USER, id);
		Iterator iter = getFoafQuery.execute().iterator();
		if(iter.hasNext()){
			return (String) iter.next();
		}
		return null;
	}
	
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.User#getTags()
	 */
	@SuppressWarnings("unchecked")
	public Collection<Tag> getTags() {
		query = "SELECT " + USERTAGGROUPRESOURCE_TAGID + " FROM " + TABLE_USERTAGGROUPRESOURCE + " WHERE " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				+ USERTAGGROUPRESOURCE_USERID + " = " + id; //$NON-NLS-1$
		GetTagsQuery getTagsQuery = new GetTagsQuery(ds, query,
				USERTAGGROUPRESOURCE_TAGID);
		Iterator iter = getTagsQuery.execute().iterator();
		if (iter.hasNext()) {
			return (Collection<Tag>) iter.next();
		}
		return new ArrayList<Tag>();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.User#getTags(net.groupme.model.Resource)
	 */
	@SuppressWarnings("unchecked")
	public Collection<Tag> getTags(Resource taggedResource) {
		query = "SELECT " + USERTAGGROUPRESOURCE_TAGID + " FROM " + TABLE_USERTAGGROUPRESOURCE + " WHERE " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				+ USERTAGGROUPRESOURCE_USERID
				+ " = " + id + " AND " + USERTAGGROUPRESOURCE_RESOURCEID + " = " + taggedResource.getId(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		GetTagsQuery getTagsQuery = new GetTagsQuery(ds, query,
				USERTAGGROUPRESOURCE_TAGID);
		Iterator iter = getTagsQuery.execute().iterator();
		if (iter.hasNext()) {
			return (Collection<Tag>) iter.next();
		}
		return new ArrayList<Tag>();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.User#getURI()
	 */
	public URI getURI() {
		try {
			return new URI(VIEW_VOCABULARY.RESTful_USER_URI_PATTERN + getUserName());//$NON-NLS-1$
		} catch (URISyntaxException e) {
			e.printStackTrace();
			return null;
		}  
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.User#getUserName()
	 */
	public String getUserName() {
		GetStringFromTableWhereIDQuery usernameQuery = new GetStringFromTableWhereIDQuery(
				ds, USER_USERNAME, TABLE_USER, id);
		return (String) usernameQuery.execute().iterator().next();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.User#getVisualizations()
	 */
	@SuppressWarnings("unchecked")
	public Collection<GroupVisualization> getVisualizations() {
		query = "SELECT " + USERGROUPVISUALIZATION_VISUALIZATION_ID + " FROM " + TABLE_USERGROUPVISUALIZATION + " WHERE " + USERGROUPVISUALIZATION_USER_ID + " = " + id; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
		GetGroupVisualizationsQuery getVisualizationsQuery = new GetGroupVisualizationsQuery(
				ds, query, USERGROUPVISUALIZATION_VISUALIZATION_ID);
		return (Collection<GroupVisualization>) getVisualizationsQuery
				.execute().iterator().next();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.User#getVisualization(net.groupme.model.Group)
	 */
	@SuppressWarnings("unchecked")
	public Collection<GroupVisualization> getVisualizations(Group group) {
		query = "SELECT " + USERGROUPVISUALIZATION_VISUALIZATION_ID + " FROM " + TABLE_USERGROUPVISUALIZATION //$NON-NLS-1$ //$NON-NLS-2$
				+ " WHERE " + USERGROUPVISUALIZATION_USER_ID + " = " + id + " AND " + USERGROUPVISUALIZATION_GROUP_ID + " = " + group.getId(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
		GetGroupVisualizationsQuery getVisualizationsQuery = new GetGroupVisualizationsQuery(
				ds, query, USERGROUPVISUALIZATION_VISUALIZATION_ID);
		return (Collection<GroupVisualization>) getVisualizationsQuery
				.execute().iterator().next();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.User#removeGroup(net.groupme.model.Group)
	 */
	public void removeGroup(Group group) throws DeleteFailedException {
		SqlUpdate su = new SqlUpdate(ds,
				"DELETE FROM " + TABLE_USERGROUP + " WHERE " //$NON-NLS-1$ //$NON-NLS-2$
						+ USERGROUP_USER_ID
						+ " = ? AND " + USERGROUP_GROUP_ID + " = ?"); //$NON-NLS-1$ //$NON-NLS-2$
		su.declareParameter(new SqlParameter("uID", Types.INTEGER)); //$NON-NLS-1$
		su.declareParameter(new SqlParameter("gID", Types.INTEGER)); //$NON-NLS-1$
		su.compile();
		try {
			Object[] oa = new Object[2];
			oa[0] = new Integer(this.id);
			oa[1] = new Integer(group.getId());
			int count = su.update(oa);
			if (count == 0)
				throw new DeleteFailedException();
		} catch (NumberFormatException e) {
			log.debug(e.getMessage());
		} 
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.User#removeTag(net.groupme.model.Tag)
	 */
	public void removeTag(Tag tag) {
		// not sure if it has to be implemented yet
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.User#removeVisualization(net.groupme.model.GroupVisualization)
	 */
	public void removeVisualization(GroupVisualization groupVisualization) {
		// not sure if it has to be implemented yet
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.User#setActualVisualization(net.groupme.model.Group,
	 *      net.groupme.model.GroupVisualization)
	 */
	public void setActualVisualization(Group group,
			GroupVisualization groupVisualization) throws UpdateFailedException {

		SqlUpdate su1 = new SqlUpdate(
				ds,
				"UPDATE " + TABLE_USERGROUPVISUALIZATION + " SET " + USERGROUPVISUALIZATION_ACTUAL //$NON-NLS-1$ //$NON-NLS-2$
						+ " = ? WHERE " + USERGROUPVISUALIZATION_USER_ID + " = ? AND " + USERGROUPVISUALIZATION_GROUP_ID + " = ? AND " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
						+ USERGROUPVISUALIZATION_ACTUAL + " = 1"); //$NON-NLS-1$
		su1.declareParameter(new SqlParameter("actual", Types.BOOLEAN)); //$NON-NLS-1$
		su1.declareParameter(new SqlParameter("userID", Types.INTEGER)); //$NON-NLS-1$
		su1.declareParameter(new SqlParameter("groupID", Types.INTEGER)); //$NON-NLS-1$
		su1.compile();

		SqlUpdate su2 = new SqlUpdate(
				ds,
				"UPDATE " + TABLE_USERGROUPVISUALIZATION + " SET " + USERGROUPVISUALIZATION_ACTUAL //$NON-NLS-1$ //$NON-NLS-2$
						+ " = ? WHERE " + USERGROUPVISUALIZATION_USER_ID + " = ? AND " + USERGROUPVISUALIZATION_GROUP_ID + " = ? AND " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
						+ USERGROUPVISUALIZATION_VISUALIZATION_ID + " = ?"); //$NON-NLS-1$
		su2.declareParameter(new SqlParameter("actual", Types.BOOLEAN)); //$NON-NLS-1$
		su2.declareParameter(new SqlParameter("userID", Types.INTEGER)); //$NON-NLS-1$
		su2.declareParameter(new SqlParameter("groupID", Types.INTEGER)); //$NON-NLS-1$
		su2
				.declareParameter(new SqlParameter(
						"visualizationID", Types.INTEGER)); //$NON-NLS-1$
		su2.compile();

		try {
			Object[] oa1 = new Object[3];
			oa1[0] = new Boolean(false);
			oa1[1] = new Integer(id);
			oa1[2] = new Integer(group.getId());
			int count = su1.update(oa1);
			Object[] oa2 = new Object[4];
			oa2[0] = new Boolean(true);
			oa2[1] = new Integer(id);
			oa2[2] = new Integer(group.getId());
			oa2[3] = new Integer(groupVisualization.getId());
			count = su2.update(oa2);
			if (count == 0)
				throw new UpdateFailedException(
						"Failed to set the new actual visualization."); //$NON-NLS-1$
		} catch (NumberFormatException e) {
			log.debug(e.getMessage());
		} 
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.Identifiable#setDescription(java.lang.String)
	 */
	public void setDescription(String description) {
		// no need to be implemented

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.User#setEmail(java.lang.String)
	 */
	public void setEmail(String email) throws UpdateFailedException {
		SqlUpdate su = new SqlUpdate(
				ds,
				"UPDATE " + TABLE_USER + " SET " + USER_EMAIL + " = ? WHERE " + USER_ID + " = ?"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
		su.declareParameter(new SqlParameter("email", Types.VARCHAR)); //$NON-NLS-1$
		su.declareParameter(new SqlParameter("ID", Types.INTEGER)); //$NON-NLS-1$
		su.compile();
		Object[] oa = new Object[2];
		oa[0] = email;
		oa[1] = new Integer(id);
		int count = su.update(oa);
		if (count == 0)
			throw new UpdateFailedException();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.User#setFirstName(java.lang.String)
	 */
	public void setFirstName(String firstname) throws UpdateFailedException {
		SqlUpdate su = new SqlUpdate(
				ds,
				"UPDATE " + TABLE_USER + " SET " + USER_FIRSTNAME + " = ? WHERE " + USER_ID + " = ?"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
		su.declareParameter(new SqlParameter("firstname", Types.VARCHAR)); //$NON-NLS-1$
		su.declareParameter(new SqlParameter("ID", Types.INTEGER)); //$NON-NLS-1$
		su.compile();
		Object[] oa = new Object[2];
		oa[0] = firstname;
		oa[1] = new Integer(id);
		int count = su.update(oa);
		if (count == 0)
			throw new UpdateFailedException();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.Identifiable#setLabel(java.lang.String)
	 */
	public void setLabel(String label) {
		// no need to be implemented

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.User#setLastName(java.lang.String)
	 */
	public void setLastName(String lastname) throws UpdateFailedException {
		SqlUpdate su = new SqlUpdate(
				ds,
				"UPDATE " + TABLE_USER + " SET " + USER_LASTNAME + " = ? WHERE " + USER_ID + " = ?"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
		su.declareParameter(new SqlParameter("lastname", Types.VARCHAR)); //$NON-NLS-1$
		su.declareParameter(new SqlParameter("ID", Types.INTEGER)); //$NON-NLS-1$
		su.compile();
		Object[] oa = new Object[2];
		oa[0] = lastname;
		oa[1] = new Integer(id);
		int count = su.update(oa);
		if (count == 0)
			throw new UpdateFailedException();
	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.User#setLastName(java.lang.String)
	 */
	public void setFoaf(String foaf) throws UpdateFailedException {
		SqlUpdate su = new SqlUpdate(
				ds,
				"UPDATE " + TABLE_USER + " SET " + "foafURL" + " = ? WHERE " + USER_ID + " = ?"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
		su.declareParameter(new SqlParameter("foafURL", Types.VARCHAR)); //$NON-NLS-1$
		su.declareParameter(new SqlParameter("ID", Types.INTEGER)); //$NON-NLS-1$
		su.compile();
		Object[] oa = new Object[2];
		oa[0] = foaf;
		oa[1] = new Integer(id);
		int count = su.update(oa);
		if (count == 0)
			throw new UpdateFailedException();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.User#setPassword(java.lang.String)
	 */
	public void setPassword(String password) throws UpdateFailedException {
		SqlUpdate su = new SqlUpdate(
				ds,
				"UPDATE " + TABLE_USER + " SET " + USER_PASSWORD + " = password(?) WHERE " + USER_ID + " = ?"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
		su.declareParameter(new SqlParameter("password", Types.VARCHAR)); //$NON-NLS-1$
		su.declareParameter(new SqlParameter("ID", Types.INTEGER)); //$NON-NLS-1$
		su.compile();
		Object[] oa = new Object[2];
		oa[0] = password;
		oa[1] = new Integer(id);
		int count = su.update(oa);
		if (count == 0)
			throw new UpdateFailedException();
	}

	/* (non-Javadoc)
	 * @see net.groupme.model.User#getPhoto()
	 */
	public String getPhoto() {
		GetStringFromTableWhereIDQuery query = new GetStringFromTableWhereIDQuery(
				ds, DATABASE_CONSTANTS.USER_PHOTO, TABLE_USER, id);
		return (String) query.execute().iterator().next();
	}

	/* (non-Javadoc)
	 * @see net.groupme.model.User#setPhoto(java.lang.String)
	 */
	public void setPhoto(String photo) {
		SqlUpdate su = new SqlUpdate(
				ds,
				"UPDATE " + TABLE_USER + " SET " + DATABASE_CONSTANTS.USER_PHOTO + " = ? WHERE " + USER_ID + " = ?"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
		su.declareParameter(new SqlParameter("photo", Types.VARCHAR)); //$NON-NLS-1$
		su.declareParameter(new SqlParameter("ID", Types.INTEGER)); //$NON-NLS-1$
		su.compile();
		Object[] oa = new Object[2];
		oa[0] = photo;
		oa[1] = new Integer(id);
		su.update(oa);
	}

}
